#include "ESPMonitor.h"
#include "ui_ESPMonitor.h"
#include <QProcess>
#include <QDebug>
#include <QMetaEnum>
#include <QDateTime>
#include <QMessageBox>
#include <QLineEdit>
#include <QBuffer>
#include <QButtonGroup>
#include <QMutex>
#include <QCloseEvent>
#include <QSettings>

Q_DECLARE_METATYPE(QSerialPortInfo)

//比较串口信息
bool operator ==(const QSerialPortInfo & first , const QSerialPortInfo & second )
{
    return first.systemLocation() == second.systemLocation();
}
/**
 * @brief 将字符串转换成人类可读的
 * @return
 */
QString convertHumanReadable(const QString& str)
{
    QBuffer strBuffer;
    strBuffer.open(QBuffer::ReadWrite);
    QDebug debug(&strBuffer);
    debug.quote().nospace().maybeQuote(' ') << str;
    return QString(strBuffer.data());
}

void ESPMonitor::setStarted(const bool &started)
{
    if( m_started != started )
    {
        m_started = started;
        emit startedChanged(m_started);
    }
}

void ESPMonitor::setSuspend(const bool &suspend)
{
    if( m_suspend != suspend )
    {
        m_suspend = suspend;
        emit suspendChanged(m_suspend);
    }
}

ESPMonitor::ESPMonitor(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::ESPMonitor)
{
    ui->setupUi(this);


    m_serial = new QSerialPort(this);

    if(!m_serial)
    {
        qDebug("无法实例化QSerialPort");
        qApp->exit(-1);
        return;
    }

    //设置界面选项

    //波特率选项
    m_serial->setBaudRate(115200);//默认值
    ui->comboBox_baudRate->setEditable(true);
    ui->comboBox_baudRate->setValidator(new QIntValidator(1,10000000,ui->comboBox_baudRate));
    ui->comboBox_baudRate->setProperty("firstAddCustomBaud",true);
    const QMetaEnum & baudRateEnum = QMetaEnum::fromType<QSerialPort::BaudRate>();
    for (int i = 0 , n = baudRateEnum.keyCount(); i < n; ++i)
    {
        if(baudRateEnum.value(i) == -1)
            continue;
        ui->comboBox_baudRate->addItem(QString(baudRateEnum.key(i)).remove("Baud"),baudRateEnum.value(i));
    }
    ui->comboBox_baudRate->setProperty("buildinBaudRateCount",ui->comboBox_baudRate->count());
    ui->comboBox_baudRate->setCurrentText(QString::number(m_serial->baudRate()));
    connect(ui->comboBox_baudRate,QOverload<int>::of(&QComboBox::currentIndexChanged),[this](int index)
    {
        auto comboBox = ui->comboBox_baudRate;

        if(!comboBox->itemData(index).isValid())
        {
            if(comboBox->property("firstAddCustomBaud").toBool())
            {
                //comboBox->insertSeparator(0);//BUG:无法添加分隔符
                comboBox->setProperty("firstAddCustomBaud",false);
            }

            //可能是新添加的波特率项,需要设置选项值
            comboBox->setItemData(comboBox->currentIndex()
                                  ,comboBox->currentText().toInt());
        }

        m_serial->setBaudRate(comboBox->itemData(index).toInt());
    });

    //校验选项
    const QMetaEnum & parityEnum = QMetaEnum::fromType<QSerialPort::Parity>();
    for (int i = 0 , n = parityEnum.keyCount(); i < n; ++i)
    {
        if(parityEnum.value(i) == -1)
            continue;
        ui->comboBox_parity->addItem(QString(parityEnum.key(i))/*.remove("Parity")*/,parityEnum.value(i));
    }
    ui->comboBox_parity->setCurrentText(parityEnum.valueToKey(m_serial->parity()));//默认值
    connect(ui->comboBox_parity,QOverload<int>::of(&QComboBox::currentIndexChanged),[this](int index)
            {
                m_serial->setParity((QSerialPort::Parity)ui->comboBox_parity->itemData(index).toInt());
            });

    //停止位选项
    const QMetaEnum & stopBitsEnum = QMetaEnum::fromType<QSerialPort::StopBits>();
    for (int i = 0 , n = stopBitsEnum.keyCount(); i < n; ++i)
    {
        if(stopBitsEnum.value(i) == -1)
            continue;
        ui->comboBox_stopbits->addItem(stopBitsEnum.key(i),stopBitsEnum.value(i));
    }
    ui->comboBox_stopbits->setCurrentText(stopBitsEnum.valueToKey(m_serial->stopBits()));//默认值
    connect(ui->comboBox_stopbits,QOverload<int>::of(&QComboBox::currentIndexChanged),[this](int index)
            {
                m_serial->setStopBits((QSerialPort::StopBits)ui->comboBox_stopbits->itemData(index).toInt());
            });

    //数据位选项
    const QMetaEnum & dataBitsEnum = QMetaEnum::fromType<QSerialPort::DataBits>();
    for (int i = 0 , n = dataBitsEnum.keyCount(); i < n; ++i)
    {
        if(dataBitsEnum.value(i) == -1)
            continue;
        ui->comboBox_databits->addItem(dataBitsEnum.key(i),dataBitsEnum.value(i));
    }
    ui->comboBox_databits->setCurrentText(dataBitsEnum.valueToKey(m_serial->dataBits()));//默认值
    connect(ui->comboBox_databits,QOverload<int>::of(&QComboBox::currentIndexChanged),[this](int index)
            {
                m_serial->setDataBits((QSerialPort::DataBits)ui->comboBox_databits->itemData(index).toInt());
            });

    //串口列表
    connect(ui->comboBox_port,QOverload<int>::of(&QComboBox::currentIndexChanged),[this](int index)
            {
                m_serial->setPort(ui->comboBox_port->itemData(index).value<QSerialPortInfo>());
                ui->comboBox_port->setToolTip(ui->comboBox_port->itemData(index,Qt::ToolTipRole).toString());
            });
    updateSerialPortList();
    if(ui->comboBox_port->count())
        ui->comboBox_port->setToolTip(ui->comboBox_port->itemData(ui->comboBox_port->currentIndex(),Qt::ToolTipRole).toString());

    //通讯历史
    //清楚历史
    connect(ui->pushButton_clean,&QPushButton::clicked,this,[this]()
    {
        ui->textEdit_history->clear();
    });

    //状态栏添加串口状态控件
    m_readHit = new QWidget();
    m_readHit->setToolTip("串口Rx状态的信号灯.");
    m_readHit->setStyleSheet("background:red");
    m_readHit->setFixedWidth(statusBar()->height()/2);
    m_writeHit = new QWidget();
    m_writeHit->setToolTip("串口Tx状态的信号灯.");
    m_writeHit->setStyleSheet("background:green");
    m_writeHit->setFixedWidth(statusBar()->height()/2);
    m_readCountLab = new QLabel();
    m_readCountLab->setToolTip("串口接收计数.");
    m_readCountLab->setMinimumWidth(50);
    m_writeCountLab = new QLabel();
    m_writeCountLab->setToolTip("串口发送计数.");
    m_writeCountLab->setMinimumWidth(50);
    updateSerialDataCount();
    m_serialPortStatusLab = new QLabel();
    m_serialPortStatusLab->setToolTip("串口的状态.");
    updateSerialPortStatus();
    m_serialPortStatusLab->setMaximumWidth(m_serialPortStatusLab->width()+100);

    //statusBar()->addPermanentWidget(new QSplitter(Qt::Horizontal),1000);
    statusBar()->addPermanentWidget(m_serialPortStatusLab,0);
    statusBar()->addPermanentWidget(m_readHit,0);
    statusBar()->addPermanentWidget(m_readCountLab,0);
    statusBar()->addPermanentWidget(m_writeHit,0);
    statusBar()->addPermanentWidget(m_writeCountLab,0);


    //串口
    //串口开关按钮
    ui->pushButton_open->setCheckable(true);
    connect(ui->pushButton_open,&QPushButton::clicked,[this](bool checked)
            {
                if(checked)
                    start();
                else
                    stop();

                ui->pushButton_open->setChecked(started());
            });
    connect(this,&ESPMonitor::startedChanged,[this](bool started)
            {
                ui->comboBox_port->setDisabled(started);//禁用端口选择
                ui->pushButton_open->setText(started?"Close":"Open");
                ui->pushButton_send->setEnabled(started);

                //停止发送
                if(!started)
                    ui->pushButton_send->setChecked(false);
                showStatusBarMessage(QString("%1 %2").arg(ui->comboBox_port->currentText())
                                         .arg(started?"Opened":"Closed"));
                updateSerialPortStatus();

                if(started)
                {
                    //重置计数
                    m_readCount = 0;
                    m_writeCount = 0;
                }
                updateSerialDataCount();
            });

    connect(this,&ESPMonitor::suspendChanged,[this](bool suspend)
            {
                ui->comboBox_baudRate->setDisabled(suspend);
                ui->comboBox_databits->setDisabled(suspend);
                ui->comboBox_stopbits->setDisabled(suspend);
                ui->comboBox_parity->setDisabled(suspend);

                ui->label_baudRate->setDisabled(suspend);
                ui->label_databits->setDisabled(suspend);
                ui->label_stopbits->setDisabled(suspend);
                ui->label_parity->setDisabled(suspend);

                ui->textEdit_history->setDisabled(suspend);
                ui->textEdit_input->setDisabled(suspend);
            });

    //串口通讯历史
    ui->textEdit_history->setReadOnly(false);

    //串口错误
    connect(m_serial,&QSerialPort::errorOccurred,[this](QSerialPort::SerialPortError error)
            {
                if(error != QSerialPort::NoError)
                {
                    QString errorMesg = m_serial->errorString();
                    stop();//关闭串口通讯
                    showMessageBox("SerialPortError",errorMesg);
                }
            });

     //串口读取
    m_readCheckTimer.callOnTimeout([this](){serialRead();});
    m_readCheckTimer.setInterval(0);
    connect(this,&ESPMonitor::startedChanged,[this](bool started)
    {
        if(started)
            m_readCheckTimer.start();
        else
            m_readCheckTimer.stop();
    });
    connect(m_serial,&QSerialPort::readyRead,[this]() { serialRead(); });

    //串口发送选项
    QButtonGroup * dataFormatGroup = new QButtonGroup(this);
    dataFormatGroup->addButton(ui->radioButton_ascii);
    dataFormatGroup->addButton(ui->radioButton_number);
    ui->radioButton_ascii->setChecked(true);
    ui->comboBox_numberBase->addItem("BIN",2); //0bnnn
    ui->comboBox_numberBase->addItem("OCT",8); //0nnn
    ui->comboBox_numberBase->addItem("DEC",10);// nnn
    ui->comboBox_numberBase->addItem("HEX",16);//0xnnn
    ui->comboBox_numberBase->addItem("MIX",0); //混合模式,自动按前缀识别
    ui->comboBox_numberBase->setCurrentText("DEC");
    ui->comboBox_numberBase->setEnabled(ui->radioButton_number->isChecked());
    connect(ui->radioButton_number,&QRadioButton::toggled,ui->comboBox_numberBase,&QComboBox::setEnabled);

    QButtonGroup * multiLineGroup = new QButtonGroup(this);
    multiLineGroup->addButton(ui->radioButton_overall);
    multiLineGroup->addButton(ui->radioButton_byline);
    ui->radioButton_overall->setChecked(true);

    ui->comboBox_lineBreak->setEditable(true);
    ui->comboBox_lineBreak->addItem("CRLF",QString("\r\n"));
    ui->comboBox_lineBreak->setItemData(ui->comboBox_lineBreak->count()-1,QString("\\r\\n"),Qt::ToolTipRole);
    ui->comboBox_lineBreak->addItem("LF",QString("\n"));
    ui->comboBox_lineBreak->setItemData(ui->comboBox_lineBreak->count()-1,QString("\\n"),Qt::ToolTipRole);
    ui->comboBox_lineBreak->setCurrentText("CRLF");
    connect(ui->comboBox_lineBreak,&QComboBox::editTextChanged,[this](const QString & text)
            {
                auto comboBox = ui->comboBox_lineBreak;
                comboBox->setItemData(comboBox->currentIndex(),text,Qt::UserRole);
                comboBox->setItemData(comboBox->currentIndex(),text,Qt::ToolTipRole);
            });

    QButtonGroup * sendModeGroup = new QButtonGroup(this);
    sendModeGroup->addButton(ui->radioButton_normal);
    sendModeGroup->addButton(ui->radioButton_reply);
    sendModeGroup->addButton(ui->radioButton_repeat);
    ui->radioButton_normal->setChecked(true);

    ui->label_interval->setEnabled(false);
    ui->spinBox_interval->setEnabled(false);
    ui->label_time->setEnabled(false);
    ui->spinBox_time->setEnabled(false);
    connect(ui->radioButton_normal,&QRadioButton::toggled,[this](bool checked)
            {
                if(checked)
                {
                    ui->label_interval->setEnabled(!checked);
                    ui->spinBox_interval->setEnabled(!checked);
                }
            });
    connect(ui->radioButton_reply,&QRadioButton::toggled,[this](bool checked)
            {
                if(checked)
                {
                    ui->label_interval->setEnabled(checked);
                    ui->spinBox_interval->setEnabled(checked);
                }
            });
    connect(ui->radioButton_repeat,&QRadioButton::toggled,[this](bool checked)
            {
                if(checked)
                {
                    ui->label_interval->setEnabled(checked);
                    ui->spinBox_interval->setEnabled(checked);
                }
                ui->label_time->setEnabled(checked);
                ui->spinBox_time->setEnabled(checked);
            });

    //串口发送按钮
    ui->pushButton_send->setEnabled(m_started);
    connect(ui->radioButton_normal,&QRadioButton::toggled,[this](bool checked){if(checked)ui->pushButton_send->setCheckable(false);});
    connect(ui->radioButton_reply,&QRadioButton::toggled,[this](bool checked){if(checked)ui->pushButton_send->setCheckable(true);});
    connect(ui->radioButton_repeat,&QRadioButton::toggled,[this](bool checked){if(checked)ui->pushButton_send->setCheckable(true);});
    connect(ui->pushButton_send,&QPushButton::clicked,[this](bool checked)
            {
                if(ui->radioButton_normal->isChecked())
                {
                    //普通发送模式,向串口输出数据
                    serialWrite(ui->textEdit_input->toPlainText().toLocal8Bit());
                }
            });

    connect(ui->pushButton_send,&QPushButton::toggled,[this](bool checked)
            {
                //ui->textEdit_input->setDisabled(checked); //屏蔽输入框
                ui->widget_sendParams->setEnabled(!checked);
                ui->pushButton_send->setText(checked?"Stop":"Send");
                if(!checked)
                    ui->pushButton_open->setChecked(false);
                if(ui->radioButton_repeat->isChecked())
                {
                    if(checked)
                    {
                        m_repartTimer.setSingleShot(false);
                        m_repartTimer.setProperty("timeLimit",ui->spinBox_time->value());
                        m_repartTimer.start(ui->spinBox_interval->value());
                    }
                    else
                    {
                        m_repartTimer.stop();
                    }
                }
            });
    //重复发送定时器
    m_repartTimer.callOnTimeout([this]()
        {
            int time = m_repartTimer.property("timeLimit").toInt();
            if(time == 0)
            {
                ui->pushButton_send->setChecked(false);
                return;
            }

            serialWrite(ui->textEdit_input->toPlainText().toLocal8Bit());

            if(time != -1)
            {
                --time;
                m_repartTimer.setProperty("timeLimit",time);
            }

            if(time == 0)
                ui->pushButton_send->setChecked(false);
        });

    //关联串口计数变化
    connect(this,&ESPMonitor::readCountChanged,&ESPMonitor::updateSerialDataCount);
    connect(this,&ESPMonitor::writeCountChanged,&ESPMonitor::updateSerialDataCount);

    //关联串口参数变化
    connect(m_serial,&QSerialPort::baudRateChanged,[this]()
            {
                updateSerialPortStatus();
                showStatusBarMessage(QString("BaudRate Changed: %1").arg(m_serial->baudRate()));
            });
    connect(m_serial,&QSerialPort::dataBitsChanged,[this,dataBitsEnum]()
            {
                updateSerialPortStatus();
                showStatusBarMessage(QString("DataBits Changed: %1").arg(dataBitsEnum.valueToKey(m_serial->dataBits())));
            });
    connect(m_serial,&QSerialPort::stopBitsChanged,[this,stopBitsEnum]()
            {
                updateSerialPortStatus();
                showStatusBarMessage(QString("StopBits Changed: %1").arg(stopBitsEnum.valueToKey(m_serial->stopBits())));
            });
    connect(m_serial,&QSerialPort::parityChanged,[this,parityEnum]()
            {
                updateSerialPortStatus();
                showStatusBarMessage(QString("Parity Changed: %1").arg(parityEnum.valueToKey(m_serial->parity())));
            });


    //界面比例分配
    ui->splitter->setStretchFactor(0,9);
    ui->splitter->setStretchFactor(1,1);


    //启动定时器,检测目标进程或者串口变动
    startIdfDetect();
    ui->pushButton_IdfDetect->setChecked(true);
    connect(ui->pushButton_IdfDetect,&QPushButton::toggled,[this](bool value)
            {
                if(value)
                    startIdfDetect();
                else
                    stopIdfDetect();
            });


    //恢复窗体状态
    QSettings settings;
    settings.beginGroup("GUI");
    restoreGeometry(settings.value("geometry").toByteArray());
    restoreState(settings.value("windowState").toByteArray());
    settings.endGroup();
}

ESPMonitor::~ESPMonitor()
{
    delete ui;
}

void ESPMonitor::start()
{
    if(!m_started && !m_suspend)
    {
        if(m_serial->open(QIODevice::ReadWrite))
            setStarted(true);
    }
}

void ESPMonitor::stop()
{
    if(m_started)
    {
        if(m_serial->isOpen())
            m_serial->close();
        setSuspend(false);
        setStarted(false);
    }
}

bool ESPMonitor::detectionProcess()
{
    QProcess cmdQuery;
#ifdef __WIN32
    QString name("idf.py.exe");
    QString output;
   // QString name("dwm.exe");
    //cmdQuery.execute("TASKLIST",QStringList()<<"/FI"<<QString("IMAGENAME eq %1").arg(name));
    cmdQuery.start("TASKLIST",QStringList()<<"/FI"<<QString("IMAGENAME eq %1").arg(name));
    if(cmdQuery.waitForFinished())
        output = QString::fromLocal8Bit(cmdQuery.readAllStandardOutput());
    qDebug().noquote() << __FUNCTION__ << output;
    return output.contains(name);
#else
    //linux平台的检查
    QString name("idf.py");
    QString query = QString("ps -ef |grep %1 |grep -v \"grep\" |wc -l").arg(name);
    QString output;
    int result = 0;
    bool ok = true;
    cmdQuery.start("bash",QStringList()<<"-c"<<query);
    if(cmdQuery.waitForFinished())
    {
        output = cmdQuery.readAllStandardOutput();
        output = output.trimmed();
        result =  output.toInt(&ok);
    }
    //qDebug().noquote()  << __FUNCTION__<< query << output << (output > 0 && ok);
    return  result > 0 && ok;
#endif

}

QString ESPMonitor::getTimestamp()
{
    return QDateTime::currentDateTime().toString("hh:mm:ss:zzz");
}

void ESPMonitor::showStatusBarMessage(const QString &text, int timeout)
{
    statusBar()->showMessage(QString("[%1] : %2")
                                 .arg(getTimestamp())
                                 .arg(text),timeout);
}

void ESPMonitor::showMessageBox(const QString &title, const QString &text)
{
    showStatusBarMessage(title + " - " + text);
    QMessageBox::warning(this,title,text);
}

void ESPMonitor::updateSerialPortList()
{
    //检查串口设备的变化
    auto serialInfos  = QSerialPortInfo::availablePorts();
    if(serialInfos != m_serialInfos)
    {
        //更新串口列表
        auto comboBox = ui->comboBox_port;
        QString currentText = comboBox->currentText();//记录先前的选择项
        comboBox->clear();
        QString toolTip("Manufacturer  \t: %1\r\n"
                        "Description   \t: %2\r\n"
                        "SerialNumber  \t: %3\r\n"
                        "VendorId      \t: %4\r\n"
                        "ProductId     \t: %5\r\n"
                        "SystemLocation\t: %6"); //工具提示
        for(const auto& info:serialInfos)
        {
            comboBox->addItem(info.portName(),QVariant::fromValue(info));
            comboBox->setItemData(comboBox->count()-1
                                  ,toolTip.arg(info.manufacturer())
                                          .arg(info.description())
                                          .arg(info.serialNumber())
                                          .arg(info.vendorIdentifier())
                                          .arg(info.productIdentifier())
                                          .arg(info.systemLocation())
                                  ,Qt::ToolTipRole);
            //标示可能的ESP Monitor端口
            if(info.vendorIdentifier() == 1027 && info.productIdentifier() == 24592)
                comboBox->setItemIcon(comboBox->count()-1, QApplication::style()->standardIcon(QStyle::SP_DialogYesButton));
        }
        comboBox->setCurrentText(currentText);//恢复选择项

        showStatusBarMessage("串口设备列表已更新!");
        m_serialInfos = serialInfos;
    }
}

void ESPMonitor::updateSerialPortStatus()
{
    //更新串口状态
    if(m_serialPortStatusLab)
        m_serialPortStatusLab->setText(QString("%1:[ %2 %3 %4 %5 ]")
                                    .arg(m_started?m_serial->portName():QString("Unknow"))
                                    .arg(m_serial->baudRate())
                                    .arg(m_serial->dataBits())
                                    .arg(m_serial->stopBits())
                                       .arg(QString(QMetaEnum::fromType<QSerialPort::Parity>().valueToKey(m_serial->parity()))[0]));
}

void ESPMonitor::updateSerialDataCount()
{
    if(m_readCountLab)
        m_readCountLab->setText(QString("Rx:%1").arg(m_readCount));
    if(m_writeCountLab)
        m_writeCountLab->setText(QString("Tx:%1").arg(m_writeCount));
}

bool ESPMonitor::serialWrite(const QByteArray &data)
{
    if(m_serial && m_serial->isOpen())
    {
        int32_t ret =  m_serial->write(data);
        if(ret != -1)
            setWriteCount(m_writeCount + ret);
        historyAppendWrite(data);
    }
}

void noBlockDelay(uint32_t ms)
{
    QEventLoop loop;
    QTimer timer;
    timer.setSingleShot(true);
    timer.callOnTimeout([&]()
    {
        loop.quit();
    });
    timer.start(ms);
    loop.exec();
}

void ESPMonitor::serialRead()
{
    static QMutex mutex;;
    if(!mutex.tryLock())
        return;

    QString data;
    int cout = 0;
    if(m_serial && m_serial->isOpen() && m_serial->bytesAvailable()) //m_serial->canReadLine()
    {
        //循环读取,直到没有数据为止
        while (m_serial->bytesAvailable() || data.contains("\n"))
        {
            data.append(m_serial->readAll());

            //提取行数据
            int nlIndex = data.indexOf("\n");
            if(nlIndex!=-1)
            {
                QString line = data.mid(0,nlIndex+1);
                data = data.mid(nlIndex+1);

                setReadCount(m_readCount + line.size());
                if(line.trimmed() != "[W][LVScreen.cpp:453] Memory used : 2396 Bytes!")
                    cout += 2;
                historyAppendRead(line.trimmed());
            }
            //等待一下看是否还有数据
            noBlockDelay(10);
        }

        if(!data.isEmpty())
        {
            setReadCount(m_readCount + data.size());
            if(data.trimmed() != "[W][LVScreen.cpp:453] Memory used : 2396 Bytes!")
                cout += 2;
            historyAppendRead(data.trimmed());
        }

        //自动回复
        if(ui->pushButton_send->isChecked() && ui->radioButton_reply->isChecked())
            QTimer::singleShot(ui->spinBox_interval->value(),[this]()
            {
               serialWrite(ui->textEdit_input->toPlainText().toLocal8Bit());
            });
    }

    mutex.unlock();
}

void ESPMonitor::historyAppendWrite(const QString &data)
{
    if(ui->checkBox_showWrite->isChecked())
    {
        QString record;
        if(ui->checkBox_showTimestamp->isChecked())
            record += QString("[%1] ").arg(getTimestamp());

        record += "Tx: ";

        if(ui->checkBox_showUnreadable->isChecked())
            record += convertHumanReadable(data);
        else
            record += data;
        ui->textEdit_history->append(record);
    }
}

void ESPMonitor::historyAppendRead(const QString &data)
{
    if(ui->checkBox_showWrite->isChecked())
    {
        QString record;
        if(ui->checkBox_showTimestamp->isChecked())
            record += QString("[%1] ").arg(getTimestamp());

        record += "Rx: ";

        if(ui->checkBox_showUnreadable->isChecked())
            record += convertHumanReadable(data);
        else
            record += data;
        ui->textEdit_history->append(record);
    }
}

void ESPMonitor::startIdfDetect()
{
    if(!m_checkTimerId)
        m_checkTimerId = startTimer(25);
    showStatusBarMessage("IDF开发工具检测开启!");
}

void ESPMonitor::stopIdfDetect()
{
    if(m_checkTimerId)
    {
        killTimer(m_checkTimerId);
        m_checkTimerId = 0;
    }
    showStatusBarMessage("IDF开发工具检测关闭!");
}

void ESPMonitor::timerEvent(QTimerEvent *event)
{
    if(event->timerId() == m_checkTimerId)
    {
        if(m_started)
        {
            //检测进程是否存在运行
            bool running = detectionProcess();

            //串口通讯已经启动未被暂停,待检测程序正在运行
            if(running && !m_suspend)
            {
                m_serial->close();
                setSuspend(true);
                showStatusBarMessage("检测到目标程序正在运行,暂停串口监视.");
            }
            //串口通讯已经启动但是被暂停,待检测程序已停止运行
            else if(!running && m_suspend)
            {
                m_serial->open(QIODevice::ReadWrite);
                setSuspend(false);
                showStatusBarMessage("检测到目标程序退出运行,恢复串口监视.");
            }
        }
        else
        {
            //更新串口列表
            updateSerialPortList();
        }
        event->accept();
    }
}

void ESPMonitor::setReadCount(const int64_t &readCount)
{
    if( m_readCount != readCount )
    {
        m_readCount = readCount;
        emit readCountChanged(m_readCount);
    }
}

void ESPMonitor::setWriteCount(const int64_t &writeCount)
{
    if( m_writeCount != writeCount )
    {
        m_writeCount = writeCount;
        emit writeCountChanged(m_writeCount);
    }
}

void ESPMonitor::closeEvent(QCloseEvent *event)
{
    QSettings settings;
    settings.beginGroup("GUI");
    settings.setValue("geometry",saveGeometry());
    settings.setValue("windowState",saveState());
    settings.endGroup();
    event->accept();
}
